{
  // #### let、const
  var a = 'Hello World'
  let b = 'Hello ES6'
  {
    var a = '你好世界'
    let b = '你好ES6'
  }
  console.log(a, b)
}
{
  // #### 解构赋值
  let [a1, a2, a3] = [0, 1, 2]
  console.log(a1, a2, a3)
  // 两边结构必需一致
  let [b1, [c1, c2], b2] = [0, [1, 2], 3]
  console.log(b1, c1, c2, b2)
  // 可以添加默认值
  let [d1, d2 = 'world'] = ['世界']
  console.log(d1, d2)
  // undefined
  let [e1, e2 = '到'] = ['找', undefined]
  console.log(e1, e2)
  // null
  let [f1, f2 = '值'] = ['空', null]
  console.log(f1, f2)
  // 对象赋值 => 被赋值变量名必须 === 对象相同key值
  let { g1, g2 } = { g1: '对', g2: '象' }
  console.log(g1, g2)
  // 先赋值情况 => 用()括号包裹
  let h
  ({ h } = { h: '先赋值' })
  console.log(h)
  // 字符串解构
  let [i, j, k] = '字符串'
  console.log(i, j, k)
}
{
  // #### 对象扩展运算符(...)
  let arr1 = ['http://', 'taobao', 'com']
  // let arr2 = arr1
  let arr2 = [...arr1]
  arr2.push('/')
  console.log(arr1, arr2)
  function test1 (...arg) {
    console.log(`对象扩展运算符：${arg}`)
  }
  test1(1, 2, 3)
  // #### rest运算符(...)
  let test2 = (a, ...arg) => {
    console.log(`rest运算符：${a}，${arg.length}`)
    for (let val of arg) {
      console.log(`for...of：${val}`)
    }
  }
  test2(1, 2, 3, 4, 5, 6)
}
{
  // #### 字符串模板(`${}`)
  let a = '技术驱动'
  let b = '数据驱动'
  // console.log(a + ' VS ' + b)
  console.log(`${a} VS ${b}`)
  // 可换行、可运算、支持标签
  document.write(`
    <div>
      <p>${a}</p>
      <p>${b}</p>
      <p>${1 + 2}</p>
    </div>
  `)
  // #### 字符串查找 includes、startWith、endWith
  let c0 = '你好这个世界，我很好！'
  let c1 = '世界'
  console.log(`indexOf：${c0.indexOf(c1) > 0}`)
  console.log(`includes：${c0.includes(c1)}`)
  console.log(`startWith：${c0.startsWith('你好')}`) // 开始有没有
  console.log(`endWith：${c0.endsWith('很好！')}`) // 结尾有没有
  // #### 字符串复制 repeat(次数)
  console.log('你好吗？'.repeat(3))
}
{
  // #### 数字操作
  let binary = 0B010101 // 二进制声明，0B做为起始表示申请二进制数据，字母B大小写均可
  console.log(`二进制：${binary}`)
  let octal = 0o666 // 八进制声明， 0o做为起始表示申请八进制数据，字母o大小写均可
  console.log(`八进制：${octal}`)
  // 判断是否数字
  let a = 11 / 4
  console.log(Number.isFinite(a))
  console.log(Number.isFinite(NaN))
  console.log(Number.isFinite(undefined))
  // 判断是否NaN
  console.log(Number.isNaN(NaN))
  console.log(Number.isNaN(1))
  // 判断是否整数
  console.log(Number.isInteger(500))
  // 转换成整型
  console.log(Number.parseInt(99.99))
  // 转换成Float
  console.log(Number.parseFloat('9' + '8.1'))
  // 取值泛围
  let c = Math.pow(2, 53) - 1 // 最大安全整数2的53次方减1
  console.log(c)
  console.log(Number.MAX_SAFE_INTEGER)  // ES6 最大安全整数
  console.log(Number.MIN_SAFE_INTEGER)  // ES6 最小安全整数
  console.log(Number.isSafeInteger(c))  // 是否为安全整数
}
{
  // #### 数组
  // json数组格式 Array.from()
  let json = {
    '0': '你的',
    '1': '我的',
    '2': '他的',
    length: 3 // 关键字段：length和长度
  }
  console.log(Array.from(json))
  // Array.of()方法
  console.log(Array.of(3, 4, 5, 6))
  // 实例方法 => find(function (值, 下标, 原型) {}) => 有任何一个满足条件则返回并终于继续查找，没有则返回undefined
  let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9] // 在实例中使用：arr.find()
  console.log(arr.find((value, index, arr) => value > 5))
  console.log(['abs', 'def', 'fga'].find((value, index, arr) => value === 'def'))
  // 实例方法：fill(替换内容, 开始位置下标, 结束位置数量(非下标而是长度))
  let arr1 = ['第一', '第二', '第三']
  console.log(arr1.fill('什么', 1, 3))
}
{
  // #### 数组循环 for...of
  let arr = ['我是', '你的', '全部', '你是', '什么']
  for (let item of arr) console.log(item) // 值
  for (let item of arr.keys()) console.log(item)  // 下标
  for (let item of arr.entries()) console.log(item)  // 键值对
  // entries() 方法
  let list = arr.entries() // 生成迭代器
  console.log('生成迭代器：', list.next().value)
  console.log('==============================')
  console.log('生成迭代器：', list.next().value)
  console.log('******************************')
  console.log('生成迭代器：', list.next().value)
  console.log('++++++++++++++++++++++++++++++')
  console.log('生成迭代器：', list.next().value)
}
{
  // #### 箭头函数 () => {}
  'use strict' // 严谨模式
  function add (a, b = 1) { // 默认值
    if (a === 0) {
      throw new Error('A is Error') // 主动抛出异常
    }
    return a + b
  }
  console.log(add(1))
  console.log(add.length) // 获得必须传递的参数个数,有默认值的参数不计入
  // () => {} 箭头函数不能当构造函数使用
  let add2 = (a, b) => a + b
  console.log(add2(1, 2))
}
{
  // #### 函数和数组
  let json = {
    a: '世界',
    b: '很美好'
  }
  // 对象的函数解构 {}，可设置默认值
  let fun = ({ a, b = 'web' }) => {
    console.log(a, b)
  }
  fun(json)
  // 数组解构
  let arr = ['前端', '教程', 'ES6']
  let funa = (a, b, c) => {
    console.log(a, b, c)
  }
  funa(...arr)
  // in 用法
  let obj = {
    a: '技术',
    b: '练习'
  }
  console.log('a' in obj) // 判断对象中是不有 a 的key值，返回布尔值
  let arr2 = ['b', 'c', '中']
  console.log(0 in arr2)  // 判断数据中是不是有空位 (下标 in 原型)
  // 遍历数组 forEach、filter、some、map
  arr.forEach((val, index) => console.log(index, val))
  arr.filter(x => console.log(x))
  arr.some(x => console.log(x))
  let tempmap = arr.map(x => 'web') // 替换
  console.log(tempmap)
  // 数组 转 字符串
  console.log(arr.toString())
  console.log(arr.join('|'))
}
{
  // #### 对象
  let name = 'web'
  let skill = 'es6'
  let obj1 = { name, skill }
  console.log(obj1)
  // Key值构建
  let key = 'skill'
  let obj2 = { [key]: 'web' }
  console.log(obj2)
  // 自定义对象方法
  let obj3 = {
    add: function (a, b) {
      return a + b
    }
  }
  console.log(obj3.add(1, 2))
  // Object.is()严格相等，=== 同值相等
  let obj4 = { name: 'word' }
  let obj5 = { name: 'word' }
  console.log(Object.is(obj4.name, obj5.name))
  // console.log(+0 === -0)  // true
  // console.log(NaN === NaN) // false
  // console.log(Object.is(+0, -0)) // false
  // console.log(Object.is(NaN, NaN)) // true
  // 合并对象 Object.assign()
  let obj6 = { obj6: 'world' }
  let obj7 = { obj7: '世界' }
  let obj8 = { obj8: '全球' }
  let obj9 = Object.assign(obj6, obj7, obj8)
  console.log(obj9)
}
{
  // #### ES6新增数据类型：Symbol
  let a = new String()
  let b = new Number()
  let c = new Boolean()
  let d = new Array()
  let e = new Object()
  let f = Symbol()  // 原始数据类型
  console.log(typeof (f))
  let g = Symbol('世界')
  console.log(g)
  console.log(g.toString())
  // 应用：key的构建
  let h = Symbol()
  let obj1 = {
    [h]: '全世界都是我的'
  }
  console.log(obj1[h])
  obj1[h] = '全球都是你的'
  console.log(obj1[h])
  // 应用：数据保护，Symbol申明的key值不会被输出
  let obj2 = {
    name: '世界',
    skill: 'web'
  }
  let age = Symbol()
  obj2[age] = 18
  console.log(obj2)
  for (let item in obj2) {
    console.log(obj2[item])
  }
  console.log(obj2[age])  // 如果要输出
}
{
  // #### Set和WeakSet数据结构
  // Set数组
  let setArr = new Set(['jspang', '技术胖', 'web', 'web', '删除我']) // 去重,set是不允许重复的，重复设置无效果
  setArr.add('技术胖')  // 重复追加无效果
  setArr.add('前端职场')  // 追加
  setArr.delete('删除我') // 删除
  console.log(setArr) // 数据结构
  console.log(setArr.has('web')) // 查找
  setArr.clear()  // 清空
  console.log(setArr) // 数据结构
  // for...of 输出
  setArr = new Set(['jspang', '技术胖', 'web', '删除我'])
  for (val of setArr) console.log(val)
  setArr.forEach(item => console.log(item))
  console.log(setArr.size)  // set属性代表长度，等同于数据的length
  // WeakSet对象
  let weakObj = new WeakSet() // 不可以直接赋值
  weakObj.add({ a: 'jspan', b: '技术胖' })  // 不允许重复值
  // ↓↓↓↓↓↓↓这种情况下不会判断为重复，因为内存空间中并不是相同的一个对象
  let obj1 = { a: 'jspan', b: '技术胖' }
  let obj2 = { a: 'jspan', b: '技术胖' }
  // 如果这样写： let obj2 = obj1 那么才算重复
  weakObj.add(obj1)
  weakObj.add(obj2)
  console.log(weakObj)
}
{
  // #### map数据类型，灵活性高
  let json = {
    name: 'jspang',
    skill: 'web'
  }
  console.log(json.name)
  // =>
  let map = new Map()
  // key 和 val 可随意改变，不需要固定先后顺序
  map.set(json, 'iam')
  map.set('jspang', json)
  console.log(map)
  // 增删查
  console.log(map.get(json))  // 得到key
  console.log(map.get('jspang'))  // 得到value
  map.delete(json)  // 删除
  map.clear() // 清空
  console.log(map.size) // size是属性,map的长度
  console.log(map.has('jspang')) // 查找用has返回的是true / false
}
{
  // 用Proxy(代理)进行预处理，增强对象和函数。生命周期或勾子函数预处理
  let obj = {
    add: v => v + 100,
    name: 'I am June.'
  }
  // console.log(obj.add(100))
  // console.log(obj.name)
  let pro = new Proxy(obj, {
    // get、set、apply
    get: (target, key, property) => {
      console.log('come in Get')
      return target[key]
    },
    set: (target, key, value, receiver) => {
      // (target, key, 要改变的值, 原始值)
      console.log(`seting ${key} = ${value}`)
      return target[key] = value
    }
    // // 对方法的处理
    // apply (target, ctx, args) {
    //   console.log('do apply')
    // }
  })
  console.log(pro.name)
  pro.name = '六月份'
  console.log(pro.name)
  // pro.add()
  // apply
  let target = function () {
    return 'I am June'
  }
  let handler = {
    // 对方法的处理
    apply (target, ctx, args) {
      console.log('do apply')
      return Reflect.apply(...arguments)
    }
  }
  let profn = new Proxy(target, handler)
  console.log(profn())
}
{
  // promise 解决多层嵌套
  let state = 1
  function step1 (resolve, reject) {
    console.log('1.开始-洗菜做饭')
    if (state === 1) {
      resolve('洗菜做饭-完成')
    } else {
      reject('洗菜做饭-出错')
    }
  }
  function step2 (resolve, reject) {
    console.log('1.开始-坐下吃饭')
    // state = 0
    if (state === 1) {
      resolve('坐下吃饭-完成')
    } else {
      reject('坐下吃饭-出错')
    }
  }
  function step3 (resolve, reject) {
    console.log('1.开始-收拾洗碗')
    if (state === 1) {
      resolve('收拾洗碗-完成')
    } else {
      reject('收拾洗碗-出错')
    }
  }
  new Promise(step1).then(function (val) {
    console.log(val)
    return new Promise(step2)
  }).then(function (val) {
    console.log(val)
    return new Promise(step3)
  }).then(function (val) {
    console.log(val)
  })
}
{
  // #### class 类
  class Coder {
    constructor (a, b) {
      this.a = a
      this.b = b
    }

    name (val) {
      console.log(val)
      return val
    }

    skill (val) {
      console.log(this.name('技术胖') + 'skill：' + val)
    }

    add () {
      return this.a + this.b
    }
  }
  let jspang = new Coder(1, 2)
  jspang.name('技术胖')
  jspang.skill('web')
  console.log(jspang.add())

  // 类的继承
  class Htmler extends Coder {
    // constructor () {}
  }
  let pang = new Htmler()
  pang.name('切图胖')
}
/* **
{
  // 此段需要要编译
  // #### 模块化：export 输出 || import 引入
  import { name } from './temp'
  console.log(name)
  // export.default 有默认选项的引入
  import def from './temp' // 不用花括号，随意取
}
*/
